#ifndef DATABASE_DATA_ELEMENT_H
#define DATABASE_DATA_ELEMENT_H

#include <memory>
#include <sqlite_modern_cpp.h>

#include "common/elements/element.h"

namespace Database
{

struct DataElement
{
    virtual ~DataElement() = default;

    virtual DataElement* clone() const = 0;
    virtual DataElement* wrap(Elements::Element* element) const = 0;

    virtual void toDatabase(sqlite::database& database) = 0;
    virtual void fromDatabase(sqlite::database& database, unsigned id) = 0;

    virtual std::vector<Elements::Element*> fromDatabaseElements(
        sqlite::database& database,
        std::vector<unsigned> ids
    ) const = 0;

    unsigned lastAddedId(sqlite::database& database) const;

    bool isNull() const;
    void setElement(Elements::Element* element);
    std::shared_ptr<Elements::Element> element() const;
    Elements::ElementType elementType() const;

    template <typename T>
    std::shared_ptr<T> elementCast() const
    {
        return std::static_pointer_cast<T>(element());
    }

    unsigned id() const;

protected:
    static std::string questionMarks(unsigned size);

protected:
    std::shared_ptr<Elements::Element> m_element;
};

typedef std::shared_ptr<DataElement> DataElementPtr;
typedef std::vector<DataElementPtr> DataElements;

} // namespace Elements

#endif // DATABASE_DATA_ELEMENT_H
